﻿#include <iostream>
#include <string>
#include <tuple>
#include <stdexcept>
#include "TypeTuple.h"
//using namespace std;

/****标准元组的使用 start********************
typedef std::tuple<int,string,string,double> Person;
void printPerson(const Person& person)
{
    auto id = std::get<0>(person);
    auto name = std::get<1>(person);
    auto addr = std::get<2>(person);
    auto age = std::get<3>(person);

    std::cout<<"Agent : "<<id<<","<<name<<","<<addr<<","
             <<age<<std::endl;
}
****标准元组的使用 end********************/


//****一个可以得到输入参数乘积的类模板 start
//非类型模板参数
template<long... nums> class Mutiply;
template<long first,long... last>
class Mutiply<first,last...>
{
public:
    static const long val = first* Mutiply<last...>::val;
};
template<> class Mutiply<>{public:static const long val = 1;};
//****一个可以得到输入参数乘积的类模板 end

//****一个可以代替pritf的模板函数 start
//递归调用结束
void HongHuoPrintf(const char* s)
{
    while (*s) {
        if(*s == '%' && *++s != '%')
            throw std::runtime_error("invalid format:missing arguments");
        std::cout<<*s++;
    }
}

//编译器为什么知道将参数包的第一个参数，作为T value传入？
template<typename T,typename... Args>
void HongHuoPrintf(const char*s,T value,Args... args)
{
    while (*s) {
        if(*s == '%' && *++s != '%'){
            std::cout<<value;
            return HongHuoPrintf(++s,args...);
        }
        std::cout<<*s++;
    }
    throw std::runtime_error("extra arguments provided to printf");
}
//****一个可以代替pritf的模板函数 end

//****一个最简单的可变参函数模板，打印每一个参数 start
void HongHuoPrintParam()
{
    std::cout<<" end"<<std::endl;
}
template<typename T,typename... Args>
void HongHuoPrintParam(T head,Args... left)
{
    std::cout<<head<<" ";
    HongHuoPrintParam(left...);
}
//****一个最简单的可变参函数模板，打印每一个参数 end


//****一个最简单的使用完美转发的例子 start
template<class F, class... Args>
void expand(const F& func, Args&&...args)
{
    std::initializer_list<int>{(func(std::forward<Args>(args)),0)...};
}
//****一个最简单的使用完美转发的例子 end

//****一个基本变参模板类 start
//前向声明
template<typename... Args>
struct Sum;

//基本定义
template<typename First, typename... Rest>
struct Sum<First, Rest...>
{
    enum { value = Sum<First>::value + Sum<Rest...>::value };
};

//递归终止
template<typename Last>
struct Sum<Last>
{
    enum { value = sizeof (Last) };
};
//****一个基本变参模板类 end

int main()
{

    //std::cout<<Mutiply<2,3,4,5>::val<<std::endl;
    //std::cout<<Mutiply<22,44,66,88,9>::val<<std::endl;

    //模板参数是数字，而不是long类型名
    std::cout<<Mutiply<2,3,4,5>::val<<std::endl;
    std::cout<<Mutiply<22,44,66,88,9>::val<<std::endl;
    //std::cout<<Mutiply<long,long,long>(12,34,25)<<std::endl;
    //std::cout<<Mutiply<23,"qwe",54>::val<<std::endl;


    //HongHuoPrintf("hello %s %s\n",std::string("world"),std::string("welcome"));
    HongHuoPrintParam(12,"good",3.14,'a');
    HongHuoPrintParam<int,std::string,int>(156,"haha",158);


    //采用auto是C++14的泛型lambda
    expand([](auto i){std::cout<<i<<std::endl;}, 1,"test",3.5);

    std::cout<<Sum<int,double,short>::value<<std::endl;
    return 0;
}
